using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SqlServer.NotificationServices;
using Microsoft.ConnectionEngine.Common;

namespace Microsoft.ConnectionEngine.Registers.Core.ServiceProvider.NotificationServices
{
    public class SystemAdapterDeliveryProtocol: IDeliveryProtocol
    {
        private SystemAdapterWS.ConnectionEngineAdapter cnAdapter;
        private NotificationStatusCallback notificationCallBack;

        #region IDeliveryProtocol Members

        /// <summary>
        /// Close a Delivery Protocol Session
        /// </summary>
        public void Close()
        {
            // No resources are held beyond the sychronous call 
            // to DeliverNotification. There are no resources for 
            // Close to release.
        }

        /// <summary>
        /// Defines the process of deliver a notification for this protocol.
        /// Uses an Adapter to send a change notification Connection Engine Message to
        /// a Service Provider defined within the body of this notification.
        /// </summary>
        /// <param name="headersList">
        /// A list of metadata that controls the delivery notification status.
        /// It is used to communicate the success of failure of the notification
        /// to the Notification Service
        /// </param>
        /// <param name="body">
        /// Contains specific information about the Service Provider to be notified
        /// and the type of metadata that changed.
        /// </param>
        public void DeliverNotification(NotificationHeaders[] headersList, string body)
        {
            System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
            doc.LoadXml(body);
            string destinationprovideridID = doc.SelectSingleNode(@"notifications/notification/ServiceProviderID").InnerText;
            string changedElement = doc.SelectSingleNode(@"notifications/notification/ChangedElement").InnerText;
            string changeNotificationMessage = String.Format(@"<HCEChangeNotification xmlns=""http://Microsoft.CollaborationEngine/Schemas""><ChangedElement>{0}</ChangedElement></HCEChangeNotification>",changedElement);

                SystemAdapterWS.ConnectionEngineMessage msg = cnAdapter.SendConnectionEngineMessage(changeNotificationMessage,9020, Guid.Empty, destinationprovideridID);
            bool result = (msg.Header.Status.Code == 0) ? true : false;
            if (notificationCallBack != null)
            {
                NotificationStatus status = new NotificationStatus(headersList[0].NotificationState,result,msg.Header.Status.Description, msg.Header.Status.Details,DateTime.UtcNow); 
                notificationCallBack(status);
            }
        }

        /// <summary>
        /// Forces finalization of any delivery process still active.
        /// </summary>
        public void Flush()
        {
            // Notification delivery by this protocol is synchronous 
            // and completes in the DeliverNotification call. There 
            // is nothing for Flush to do.
        }

        /// <summary>
        /// Initializes the Delivery Protocol Class
        /// </summary>
        /// <param name="channelArgs">Defines all the arguments needed to initialize the delivery protocol</param>
        /// <param name="multicast">Defines if this protocol allows multicast or not.</param>
        /// <param name="notificationStatusCallback">Defines the object to be used for Notification Status Callbacks.</param>
        public void Initialize(System.Collections.Specialized.StringDictionary channelArgs, bool multicast, NotificationStatusCallback notificationStatusCallback)
        {

            if (channelArgs.Count != 3)
            {
                throw new ApplicationException("Channel didn't provide enough initialization arguments. Expected 03.");
            }
            else
            {
                cnAdapter = new SystemAdapterWS.ConnectionEngineAdapter();
                cnAdapter.Url = channelArgs["SystemAdapterWebServiceURL"];
                string username = channelArgs["SystemAdapterWebServiceUserName"];
                string password = channelArgs["SystemAdapterWebServicePassword"];
                if (!String.IsNullOrEmpty(username) && !String.IsNullOrEmpty(password))
                    cnAdapter.Credentials = new System.Net.NetworkCredential(username, password);

                //Work Item ID: 1236
                //Modified By: SachinJo
                //System.Net.WebProxy.GetDefaultProxy is obsolete using System.Net.WebRequest.DefaultWebProxy instead.
                //cnAdapter.Proxy = System.Net.WebProxy.GetDefaultProxy();
                cnAdapter.Proxy = System.Net.WebRequest.DefaultWebProxy;

                cnAdapter.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;

                notificationCallBack = notificationStatusCallback;
            }
            //if (channelArgs.Count != 13)
            //{
            //    throw new ApplicationException("Channel didn't provide enough initialization arguments. Expected 13.");
            //}
            //else
            //{
            //    try
            //    {
            //        string hceserviceurl = channelArgs["ConnectionEngineServiceURL"];
            //        string hceusername = channelArgs["ConnectionEngineUserName"];
            //        string hcepassword = channelArgs["ConnectionEnginePassword"];
            //        string hsdserviceproviderid = channelArgs["ServiceProviderRegisterServiceProviderID"];
            //        string hsdencryptiontype = channelArgs["ServiceProviderRegisterEncryptionType"];
            //        string hsdpublickey = channelArgs["ServiceProviderRegisterPublicKey"];
            //        string csaserviceproviderid = channelArgs["SystemAdapterServiceProviderID"];
            //        string csawebserviceurl = channelArgs["SystemAdapterWebServiceURL"];
            //        string csaencryptionalgorithm = channelArgs["SystemAdapterEncryptionAlgorithm"];
            //        string csapublickey = channelArgs["SystemAdapterPublicKey"];
            //        string csaprivatekey = channelArgs["SystemAdapterPrivateKey"];
            //        string csaclientcertificate = channelArgs["SystemAdapterClientCertificate"];
            //        string messagehandlerlist = channelArgs["SystemAdapterMessageHandlerList"];

            //        if (cnAdapter == null)
            //        {
            //            cnAdapter = new ChangeNotificationAdapter(hceserviceurl, hceusername, hcepassword, hsdserviceproviderid,
            //                                                      hsdencryptiontype, hsdpublickey, csaserviceproviderid, csawebserviceurl,
            //                                                      csaencryptionalgorithm, csapublickey, csaprivatekey, csaclientcertificate, messagehandlerlist);
            //        }
            //        notificationCallBack = notificationStatusCallback;
            //    }
            //    catch (Exception e)
            //    {
            //        throw e;
            //    }
            //}
        }

        #endregion
    }
}
